package com.niit.repository.controller;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import com.niit.repository.bean.User;
import com.niit.repository.service.UserService;

@RestController
public class UserController {

    @Autowired
    UserService userService;
    
    @SuppressWarnings("serial")
	@GetMapping("/users")
    public  Map<String, Object> findAll(Integer page, Integer size, String sortName, String sortOrder, String searchName, String searchAddr, String searchPhone){
    	PageRequest pageable = null;
        if(sortName != null && !sortName.isEmpty()) { 
            Order order1 = new Order(sortOrder.equalsIgnoreCase("desc")?Direction.DESC:Direction.ASC, sortName);
            Sort sort =Sort.by(order1);
            // 后台分页,以0为起始页,故页号page要减一
            pageable = PageRequest.of(page-1, size, sort);
        }else        
            pageable = PageRequest.of(page-1, size);// 不需排序,仅分页
        

        // 创建内部匿名的Specification接口实现类
        Specification<User> spec = new Specification<User>() {
			/*
             * @Param root: Root接口，主要用于处理实体和字段、实体与实体之间的关系。除了取字段的操作以外，还可以做join操作
             * 
             * @Param query: CriteriaQuery接口，主要用于对查询结果的处理，包括groupBy、orderBy、having、distinct等操作
             * 
             * @Param criteriaBuilder: CriteriaBuilder接口，主要用于各种条件查询、模拟sql函数等
             * 
             * @Return Predicate: 表示查询条件
             */
            @SuppressWarnings("unchecked")
            @Override
            public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
            	List<Predicate> predicates = new ArrayList<>();

            	if(searchName!=null && !searchName.trim().isEmpty()) {
                	// 查询条件 user_name like %searchName%
            		predicates.add(criteriaBuilder.like(root.get("userName").as(String.class), "%"+searchName+"%"));
                }
                if(searchPhone!=null && !searchPhone.trim().isEmpty()) {
                	// 查询条件 phone like %searchAddr%
                	predicates.add(criteriaBuilder.like(root.get("phone").as(String.class), "%"+searchPhone+"%"));
                }
                if(searchAddr!=null && !searchAddr.trim().isEmpty()) {
                	// 查询条件 address like %searchAddr%
                	predicates.add(criteriaBuilder.like(root.get("address").as(String.class), "%"+searchAddr+"%"));
                }

                // 组合查询条件
                return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
            }

        };

        // Specification查询主要用于复杂查询。通过三个参数的组合，可以实现基本上绝大部分sql能实现的复杂查询，且基于Java代码，具有较好的可读性。

        Page<User> pageObj = userService.findAll(spec, pageable);

        System.out.println("总记录数：" + pageObj.getTotalElements());
        System.out.println("当前页号：" + (pageObj.getNumber() + 1));// 加一后就是从1开始的页号
        System.out.println("总页数：" + pageObj.getTotalPages());
        System.out.println("当前页的内容：" + pageObj.getContent());
        System.out.println("当前页的记录数：" + pageObj.getNumberOfElements());

        Map<String, Object> result = new HashMap<String,Object>();
        result.put("total", pageObj.getTotalElements());
        result.put("rows",pageObj.getContent());
        return result;
        
    }
}

